package com.huawei.eidc.message;

import java.util.Iterator;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.huawei.eidc.slee.security.Base64;
import com.huawei.eidc.slee.security.DESTools;
import com.huawei.eidc.slee.security.MD5;

public class EncodeUtil {

	 /**
     * 对字符串进行加密
     * 1. 数字签名保证信息完整性
     * 2. 3DES加密保证不可阅读性
     * 3. BASE64编码
     * Base64( 3DES( MD5( 消息体 ) + 消息体)
     * @param str String
     * @return String
     */
    public static String encrypt(String str,String desSecret)
    {
        String body = null;

        try {
            DESTools des = DESTools.getInstance(desSecret);
            System.out.println("加密前的消息体:");
            System.out.println(str);
            String md5str = MD5.md5(str)+str;
            System.out.println("MD5后的字符串:");
            System.out.println(md5str);
            byte[] b = des.encrypt(md5str.getBytes("UTF8"));
            System.out.println("DES后的字节数组:");
            printBytes(b);
            body = Base64.encode(b);
            System.out.println("Base64后的字符串:");
            System.out.println(body);
        } catch (Exception ex) {

        }
        return body;
   }
    
    /**
     * 对字符串进行解密
     * Base64( 3DES( MD5( 消息体 ) + 消息体) 逆操作
     * @param str String
     * @return String
     * 解密时判断数据签名，如果不匹配则返回null
     */
    public static String decrypt(String str,String desSecret)
    {
        String body = null;
        try {
            DESTools des = DESTools.getInstance(desSecret);
            System.out.println("对方传来的消息源串：");
            System.out.println(str);
            byte[] b = Base64.decode(str);
            System.out.println("Base64解码之后的结果：");
            printBytes(b);
            String md5body = new String(des.decrypt(b),"UTF8");
            System.out.println("3DES解密后的结果：");
            System.out.println(md5body);
            if(md5body.length()<32)
            {
                System.out.println("错误！消息体长度小于数字签名长度!");
                return null;
            }
            String md5Client = md5body.substring(0,32);
            System.out.println("对方传来的数字签名：");
            System.out.println(md5Client);
            body = md5body.substring(32);
            System.out.println("对方传来的消息体：");
            System.out.println(body);
            String md5Server = MD5.md5(body);
            System.out.println("我方对传来消息的数字签名：");
            System.out.println(md5Server);
            if(!md5Client.equals(md5Server))
            {
                System.out.println("错误！数字签名不匹配:");
                return null;
            }
        } catch (Exception ex) {

        }
        return body;
    }

    /**
     * 打印字节数组
     * @param b byte[]
     */
    public static void printBytes(byte[] b)
    {
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<b.length;i++)
        {
            sb.append("["+b[i]+"],");
            if(i%15==0)
            {
                sb.append("\n");
            }
        }
        System.out.println(sb);
    }
    
    /**
     * 对传入打包好的整个消息进行解码
     * 分别对头部和尾部进行处理
     * @param str String 打包好的消息字符串
     * @param desSecret String 密钥
     * @return boolean 返回解包成功失败
     */
    public static boolean decode(String str, String desSecret)
    {
        if (str == null)
        {
            return false;
        }
        try{
            org.dom4j.Document document = DocumentHelper.parseText(str);
            System.out.println();
            System.out.println("消息头...");
            System.out.println();

            Element head = document.getRootElement().element("HEAD");
            System.out.println("CODE:");
            System.out.println(head.element("CODE").getTextTrim());
            System.out.println("SID:");
            System.out.println(head.element("SID").getTextTrim());
            System.out.println("TIMESTAMP:");
            System.out.println(Long.parseLong(head.element("TIMESTAMP").getTextTrim()));
          
            String strBody = document.getRootElement().element("BODY").getTextTrim();
            System.out.println("BODY:");
            System.out.println(strBody);
            System.out.println();
            System.out.println("消息头结束.");
            System.out.println();

            System.out.println("消息体...");
            System.out.println();
            if ( decodeBody(strBody,desSecret) ) {
                System.out.println("decodeBody OK!");
            }
            else {
                System.out.println("decodeBody ERROR!");
                return false;
            }
            System.out.println();
            System.out.println("消息体结束.");
            System.out.println();
        }
        catch(Exception ex)
        {
            return false;
        }
        return true;
    }
    
    /**
     * 对消息体进行解包识别输出实例
     * @param str String  消息体字符串
     * @param desSecret String 密钥
     * @return boolean 解包成功失败
     */
    public static boolean decodeBody(String str, String desSecret)
    {
        String bodyStr = decrypt(str,desSecret);
        if (bodyStr == null) return false;
        try{
            org.dom4j.Document document = DocumentHelper.parseText(bodyStr);
            Element body = document.getRootElement();
            Iterator it = body.elementIterator("SECTION");
            while(it.hasNext())
            {
               Element es = (Element)it.next();
               System.out.println("NAME="+es.elementText("NAME"));
               System.out.println("VALUE="+es.elementText("VALUE"));
            }
        }
        catch(Exception ex)
        {
            return false;
        }
        return true;
    }

}
